home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
SOUND
/
RAVELUTL.ARJ
/
HARMONIZ.MA
< prev
next >
Wrap
Text File
|
1989-08-03
|
14KB
|
510 lines
export
modalHarmonize,
chordHarmonize,
parallelHarmonize,
majorHarmonize
end
#
# closed voicing harmonization.
#
# Routines here basically give closed voicings via
# a harmonization of a high melody voice. No attention
# is paid to voice leading from previous chord.
#
# routines for harmonizing a melody note
#
# 1. modalHarmonize - produce chord in scale that corresponds to
# modal harmony; e.g., given B in C IONIAN scale returns Major7, C,E,G,B
# given C in C IONIAN scale returns Dminor7,
# LD,LF,LA,C.
# Can handle modal scales only.
#
# 2. chordHarmonize - harmonize melody note according to current chord.
# chord passed in is used and may be inverted.
# Handles most (if not all) chords.
#
# 3. parallelHarmonize - Parallel motion may be supported
# by saving the last melody note
# and the last returned harmony chord and then subtracing the
# difference between the new melody note and last melody note
# to produce the new harmony chord. A routine is provided to do this.
#
# 4. majorHarmonize - harmonizes melody note based on root I ii iii IV V vi vii0
# harmonic assumption. Thus if used be careful of harmonic
# root; e.g., if tracking via chord then harmonize as follows;
#
# major - I, IV
# minor - ii, iii, vi
# dom - V
# dim - vii0
#
# 5. harmonizeDominant() - different close harmony for dominant - uses
# flatted 5th rule (dom7 on minor 2nd of root). NOT IMPLEMENTED.
#
# 6. minorHarmonize - similar to majorHarmonize but use traditional
# minor chords. NOT IMPLEMENTED.
# turn on for standalone test
# otherwise include these two before this include library.
@include \mh\scales.mh
@include \mh\chords.mh
#
# modalHarmonize()
#
# Given the following inputs:
# pointer to integer output array of size 3
# scaleCount - number of indices into scale array
# pointer to scale array
# root offset - i.e., offset value for current note
# where note is formed by octave+root+offset
#
# produce a "harmony" chord from the inputs.
# We find the associated "offsets" down a third, fifth,
# and seventh from the input offset which is assumed to
# be the top melody note.
#
# The returned offsets taken together with the input offset
# can be used to form a 4 note harmonized chord. This
# will be built from the associated scale and thus represents
# a simple harmonization. The chord is built as follows:
# melody = octave+root+offset
# third down = octave+root+output[2]
# fifth down = octave+root+output[1]
# seventh down = octave+root+output[0]
#
# CAVEATS:
# This routine makes sense for normal scales. If
# the scales are far out; so will be the results.
#
# It also isn't very interesting to call this over
# and over again for a harmonization. The
# high level routines may use this as a basic tool,
# but should also use a certain amount of diminished
# and/or same chord (if Dom7, then use Dom7) to
# provide variety.
#
# Also:
# . not suitable for 1st/last note in chord.
# . not normal for "thickened" line.
#
riff modalHarmonize(int vector output, scaleCount, vector scale, offset)
# vector output, lower 3 notes of chord, 4 voice chord including top note
# note that this must be an integer vector due to negative
# subtraction trick, below.
# scale index
# note offset (note is assumed to be octave+root+rootOffset)
int thirdOffset
int fifthOffset
int seventhOffset
int i
# find offset value
for ( i = 0; i < scaleCount; i++)
if (scale[i] == offset)
break
end
end
# ASSERTION
if ( i == scaleCount)
void printf("did not find rootOffset in scale\n")
return(0)
end
# i is associated scale index
# first third down
thirdOffset = i - 2
if (thirdOffset < 0)
thirdOffset = scaleCount + thirdOffset
output[2] = scale[thirdOffset] - 12
else
output[2] = scale[thirdOffset]
end
# fifth down
fifthOffset = i - 4
if (fifthOffset < 0)
fifthOffset = scaleCount + fifthOffset
output[1] = scale[fifthOffset] - 12
else
output[1] = scale[fifthOffset]
end
# 7th down
seventhOffset = i - 6
if (seventhOffset < 0)
seventhOffset = scaleCount + seventhOffset
output[0] = scale[seventhOffset] - 12
else
output[0] = scale[seventhOffset]
end
end
#
# chordHarmonize()
# harmonize a melody note to a certain CHORD pattern
#
# returns chord with ROOT; E.g., if C chord and D melody
# note; you get back a harmony chord in closed position
# that has a C root. The chord maybe inverted. The chord
# notes are chosen as close as possible down from
# the melody note. No attention is giving to voice leading.
#
# Can handle 2,3,and more note chords. If chord is bigger
# than 3 notes; the chordSize is used for determining lower
# offsets returned.
#
riff chordHarmonize(int vector output, melOffset, vector chordInput, chordSize)
# output - array for 3 three lower harmony voices
# melOffset - (octave,root,offset) form of lead melody note.
# vector chordInput - row pointer to chord in chordNotes array.
# chordSize - max notes in chord.
#
# returns:
# number of notes used in output array. E.g., 3 means
# 3 voice chord. 2 means 2 voice chord.
int chordIndex
int noback
# map offset into chord index
# we find first chord degree greater than or equal to
# melody offset
for ( chordIndex = 0; chordIndex < chordSize; chordIndex++)
if (chordInput[chordIndex] >= melOffset)
break
end
end
if (chordIndex == chordSize)
chordIndex--
end
#void printf("chordSize %d, chordIndex %d [] %d, melOffset %d\n", chordSize, chordIndex, chordInput[chordIndex], melOffset)
# chordIndex is first chord degree GREATER than or same as melody note
# this means that previous chord degree is less than melody note.
switch(chordSize)
# 2 note chords
case 2:
noback = 3 - chordIndex
switch(noback)
# 0 can't happen
case 1:
output[2] = chordInput[1]
output[1] = chordInput[0] # unison
output[0] = chordInput[1] - 12
end
case 2:
output[2] = chordInput[0] # unison
output[1] = chordInput[1] - 12
output[0] = chordInput[0] - 12
end
# complete octave down
case 3:
output[2] = chordInput[1] - 12
output[1] = chordInput[0] - 12
output[0] = chordInput[1] - 24
end
default:
void printf("%d %d invalid interval calculation\n",chordSize,chordIndex)
end
end
end
# 3 note chords
case 3:
noback = 3 - chordIndex
switch(noback)
case 0:
output[2] = chordInput[2] # 5th
output[1] = chordInput[1] # 3rd
output[0] = chordInput[0] # unison
end
case 1:
output[2] = chordInput[1] # 3rd
output[1] = chordInput[0] # unison
output[0] = chordInput[2] - 12 # 5th
end
case 2:
output[2] = chordInput[0] # unison
output[1] = chordInput[2] - 12 # 5th
output[0] = chordInput[1] - 12 # 3rd
end
# complete octave down
case 3:
output[2] = chordInput[2] - 12 # 5th
output[1] = chordInput[1] - 12 # 3rd
output[0] = chordInput[0] - 12 # unison
end
default:
void printf("%d %d invalid interval calculation\n",chordSize,chordIndex)
end
end
end
# more than 3
default:
noback = 3 - chordIndex
switch(noback)
case 0:
output[2] = chordInput[2] # 5th
output[1] = chordInput[1] # 3rd
output[0] = chordInput[0] # unison
end
case 1:
output[2] = chordInput[1] # 3rd
output[1] = chordInput[0] # unison
output[0] = chordInput[chordSize-1] - 12 # 7th
end
case 2:
output[2] = chordInput[0] # unison
output[1] = chordInput[chordSize-1] - 12 # 7th
output[0] = chordInput[chordSize-2] - 12 # 5rd
end
# complete octave down
case 3:
output[2] = chordInput[chordSize-1] - 12 # 7th
output[1] = chordInput[chordSize-2] - 12 # 5th
output[0] = chordInput[chordSize-3] - 12 # 3rd
end
default:
void printf("%d %d invalid interval calculation\n",chordSize,chordIndex)
end
end
end
end
end
#
# parallelHarmonize()
#
# return parallel harmony chord.
#
# Caveats:
# You can't do it on the first chord obviousally
#
# difference. positive or negative offset from previous melody note
# e.g., C -> D, then 2, C -> LBb then -2. should be new - old.
riff parallelHarmonize(int vector output, melOffset, difference)
output[0] = output[0] + difference
output[1] = output[1] + difference
output[2] = output[2] + difference
return(melOffset+difference)
end
#
# majorHarmonize
#
# expect offset that corresponds to major scale offsets.
# returns harmony chord based on standard major root harmony.
# I ii iii IV V vi vii0.
#
# Chords returned are basically either major or dominant
# harmony (not too racy here).
#
riff majorHarmonize(int vector output, offset)
# vector output, lower 3 notes of chord, 4 voice chord including top note
# note that this must be an integer vector due to negative
# subtraction trick, below.
# offset - IONIAN scale offset 0,2,4,5,7,9,11
# (unison)0 - returns major chord
# (2nd) 2 - returns vii0 OR V7 (random)
# (3rd) 4 - returns major chord
# (4th) 5 - returns vii0 or V7
# (5th) 7 - returns major
# (6th) 9 - returns vii0/ii
# (7th) 11 - returns major
#
int rval
rval = mchoose(0,1)
switch(offset)
# unison, return Major inverted on 3rd
case 0:
output[0] = {-8} # third
output[1] = {-5} # fifth
if (rval)
output[2] = {-3} # sixth
else
output[2] = {-1} # seventh
end
end
# 2nd, return Dom7 or vii0 half/dim.
# Dom7 is inverted on 7th, vii inverted on 5th
case 2:
output[0] = {-7} # fourth
if (rval)
output[1] = {-5} # fifth
else
output[1] = {-3} # sixth
end
output[2] = {-1} # seventh
end
# 3rd, return major 6/7 inverted on 5rd
case 4:
output[0] = {-5} # 5th
if (rval)
output[1] = {-3} # 6th
else
output[1] = {-1} # 7th
end
output[2] = 0 #unison
end
# 4th, return Dom/half-dim. Dom rooted on dom unison,
# half-dim rooted on 7th
case 5:
if (rval)
output[0] = {-5} # 5th
else
output[0] = {-3} # 6th
end
output[1] = {-1} #7th
output[2] = 2 # 2nd
end
# 5th, return major chord
case 7:
if (rval)
output[0] = {-3} # 6th
else
output[0] = {-1} # 7th
end
output[1] = 0 # unison
output[2] = 4 # 3rd
end
# 6th, return half/dim OR minor 2nd.
case 9:
if (rval)
output[0] = {-1} # 7th
else
output[0] = 0
end
output[1] = 2 # 2nd
output[2] = 5 # 4th
end
# 7th, return major or Dom7
case 11:
if (rval)
# major
output[0] = 0
output[1] = 4 #3rd
output[2] = 7 #5th
else
# dom7
output[0] = 2 #2nd
output[1] = 5 #4th
output[2] = 7 #5th
end
end
default:
void printf("unknown offset\n")
end
end
end
# TEST ROUTINES
# commented out at the moment.
###############################################################
#int harmChord[3]
#riff testHarmonize()
# int i
# int scaleIndex
# int melOffset
#
# for ( scaleIndex = 6; scaleIndex >= 0; scaleIndex--)
# # pass the following
# # 1. pointer to output vector of size 3
# # 2. size of scale
# # 3. pointer to scale offset row
# # 4. current roff value
# melOffset = baseScale[IONIAN][scaleIndex]
# void chordHarmonize(&harmChord, melOffset, &chordNotes[Major6], chordSizes[Major6])
# # print out chord from bass to melody
# for ( i = 0; i < 3; i++)
# void printf("%n,", C+harmChord[i])
# C+harmChord[i] 0,q 100
# end
# void printf("%n\n",C+melOffset)
# C+melOffset q 100
# end
#end
#
#int aChord[3]
#riff testModalHarmonize()
# int i
# int scaleIndex
#
# for ( scaleIndex = 6; scaleIndex >= 0; scaleIndex--)
# # pass the following
# # 1. pointer to output vector of size 3
# # 2. size of scale
# # 3. pointer to scale offset row
# # 4. current roff value
# void modalHarmonize(&aChord, scaleSizes[DORIAN], &baseScale[DORIAN], baseScale[DORIAN][scaleIndex])
# for ( i = 0; i < 3; i++)
# void printf("%n,", C+aChord[i])
# C+aChord[i] 0,q 100
# end
# void printf("%n\n",C+baseScale[DORIAN][scaleIndex])
# C+baseScale[DORIAN][scaleIndex] q 100
# end
#end
#
#int hChord[3]
#riff testParallelHarmonize()
# int i
# int scaleIndex
# int melOffset
# int lastMelOffset
# int difference
#
# # play first chord
# lastMelOffset = baseScale[IONIAN][6]
# hChord[2] = baseScale[IONIAN][4]
# hChord[1] = baseScale[IONIAN][2]
# hChord[0] = baseScale[IONIAN][0]
# for ( i = 0; i < 3; i++)
# void printf("%n,", C+hChord[i])
# C+hChord[i] 0,q 100
# end
# void printf("%n\n",C+lastMelOffset)
# C+lastMelOffset q 100
#
# for ( scaleIndex = 5; scaleIndex >= 0; scaleIndex--)
# # pass the following
# # 1. pointer to output vector of size 3
# # 2. size of scale
# # 3. pointer to scale offset row
# # 4. current roff value
# melOffset = baseScale[IONIAN][scaleIndex]
# difference = melOffset - lastMelOffset
# void parallelHarmonize(&hChord, melOffset, difference)
# for ( i = 0; i < 3; i++)
# void printf("%n,", C+hChord[i])
# C+hChord[i] 0,q 100
# end
# void printf("%n\n",C+baseScale[IONIAN][scaleIndex])
# C+baseScale[IONIAN][scaleIndex] q 100
# lastMelOffset = melOffset
# end
#end
#int rChord[3]
#vco testRoot()
# int i
# int index
# int melOffset
#
#
# for ( index = 0; index < 7; index++)
# melOffset = baseScale[IONIAN][index]
# void majorHarmonize(&rChord, melOffset)
# for ( i = 0; i < 3; i++)
# void printf("%n,", C+rChord[i])
# C+rChord[i] 0,q 100
# end
# void printf("%n\n",C+melOffset)
# C+melOffset q 100
# end
#end